using Admin.NET.Application.Entity;
using Admin.NET.Core;
using Furion.DependencyInjection;
using Microsoft.AspNetCore.Authorization;
using SqlSugar;

namespace Admin.NET.Application.Service.Report;

/// <summary>
/// 出库流水报表服务（仅出库）
/// </summary>
[ApiDescriptionSettings("Report", Name = "outFlow", Order = 901)]
[Route("api/report/outFlow")]
[AllowAnonymous]
public class OutFlowReportService : IDynamicApiController, ITransient
{
    private readonly ISqlSugarClient _sqlSugarClient;

    public OutFlowReportService(ISqlSugarClient sqlSugarClient)
    {
        _sqlSugarClient = sqlSugarClient;
    }

    /// <summary>
    /// 出库流水分页查询（按时间范围、订单号、客户、出库类型、仓库、经办人、制单人/制单时间等筛选）
    /// </summary>
    [HttpPost("page")]
    public async Task<object> Page([FromBody] GetOutFlowInput input)
    {
        DateTime? outStart = input.StartTime?.Date;
        DateTime? outEnd = input.EndTime?.Date;
        if (outEnd != null) outEnd = outEnd.Value.AddDays(1).AddTicks(-1);

        DateTime? createStart = input.CreateStartTime?.Date;
        DateTime? createEnd = input.CreateEndTime?.Date;
        if (createEnd != null) createEnd = createEnd.Value.AddDays(1).AddTicks(-1);

        var query = _sqlSugarClient.Queryable<Sysoutstockorder>()
            .LeftJoin<SysOrg>((o, org) => o.OrgId == org.Id)
            .WhereIF(outStart != null, (o, org) => o.OutDate >= outStart)
            .WhereIF(outEnd != null,   (o, org) => o.OutDate <= outEnd)
            .WhereIF(createStart != null, (o, org) => o.CreateTime >= createStart)
            .WhereIF(createEnd != null,   (o, org) => o.CreateTime <= createEnd)
            .WhereIF(!string.IsNullOrWhiteSpace(input.OrderNo), (o, org) => o.Code.Contains(input.OrderNo!.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.OutType), (o, org) => o.OutType!.Contains(input.OutType!.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.WarehouseName), (o, org) => o.WarehouseName!.Contains(input.WarehouseName!.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.CustomerName), (o, org) => o.CustomerName!.Contains(input.CustomerName!.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.ContactPerson), (o, org) => o.ContactPerson!.Contains(input.ContactPerson!.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.CreateUserName), (o, org) => o.CreateUserName!.Contains(input.CreateUserName!.Trim()))
            .WhereIF(input.OrgId != null, (o, org) => o.OrgId == input.OrgId)
            .WhereIF(!string.IsNullOrWhiteSpace(input.GoodsOrCategory), (o, org) => o.GoodsName!.Contains(input.GoodsOrCategory!))
            .OrderBy((o, org) => o.OutDate, OrderByType.Desc)
            .Select((o, org) => new OutFlowRowOutput
            {
                BillNo = o.Code,
                BizTime = o.OutDate,
                OutType = o.OutType,
                CustomerName = o.CustomerName,
                GoodsName = o.GoodsName,
                WarehouseName = o.WarehouseName,
                Quantity = o.OutQuantity,
                Amount = o.OutbouAmount,
                UnitPrice = SqlFunc.IIF(o.OutQuantity == 0, 0, o.OutbouAmount / (decimal)o.OutQuantity),
                OperatorName = o.ContactPerson,
                MakerName = o.CreateUserName,
                DeptName = org.Name,
                MakeTime = o.CreateTime,
                AuditorName = o.UpdateUserName,
                AuditTime = o.UpdateTime,
                Remark = o.Remark
            });

        var total = new RefAsync<int>();
        var list = await query.ToPageListAsync(input.Page, input.PageSize, total);

        return new
        {
            Items = list,
            Total = total.Value,
            Page = input.Page,
            PageSize = input.PageSize
        };
    }

    /// <summary>
    /// 出库流水统计（单据数、出库数量、出库金额）
    /// </summary>
    [HttpPost("stats")]
    public async Task<OutFlowStatsOutput> Stats([FromBody] GetOutFlowInput input)
    {
        DateTime? outStart = input.StartTime?.Date;
        DateTime? outEnd = input.EndTime?.Date;
        if (outEnd != null) outEnd = outEnd.Value.AddDays(1).AddTicks(-1);

        var q = _sqlSugarClient.Queryable<Sysoutstockorder>()
            .WhereIF(outStart != null, x => x.OutDate >= outStart)
            .WhereIF(outEnd != null,   x => x.OutDate <= outEnd)
            .WhereIF(!string.IsNullOrWhiteSpace(input.OrderNo), x => x.Code.Contains(input.OrderNo!))
            .WhereIF(!string.IsNullOrWhiteSpace(input.OutType), x => x.OutType!.Contains(input.OutType!))
            .WhereIF(!string.IsNullOrWhiteSpace(input.WarehouseName), x => x.WarehouseName!.Contains(input.WarehouseName!))
            .WhereIF(!string.IsNullOrWhiteSpace(input.CustomerName), x => x.CustomerName!.Contains(input.CustomerName!))
            .WhereIF(!string.IsNullOrWhiteSpace(input.ContactPerson), x => x.ContactPerson!.Contains(input.ContactPerson!))
            .WhereIF(!string.IsNullOrWhiteSpace(input.GoodsOrCategory), x => x.GoodsName!.Contains(input.GoodsOrCategory!));

        return new OutFlowStatsOutput
        {
            OrdersCount = await q.CountAsync(),
            GoodsQuantity = await q.SumAsync(x => (decimal)x.OutQuantity),
            GoodsAmount = await q.SumAsync(x => x.OutbouAmount)
        };
    }
}

public class GetOutFlowInput
{
    public DateTime? StartTime { get; set; }
    public DateTime? EndTime { get; set; }
    public DateTime? CreateStartTime { get; set; }
    public DateTime? CreateEndTime { get; set; }
    public string? OrderNo { get; set; }
    public string? CustomerName { get; set; }
    public string? ContactPerson { get; set; }
    public string? OutType { get; set; }
    public string? WarehouseName { get; set; }
    public string? CreateUserName { get; set; }
    public long? OrgId { get; set; }
    public string? GoodsOrCategory { get; set; }
    public int Page { get; set; } = 1;
    public int PageSize { get; set; } = 10;
}

public class OutFlowRowOutput
{
    public string? BillNo { get; set; }
    public DateTime BizTime { get; set; }
    public string? OutType { get; set; }
    public string? CustomerName { get; set; }
    public string? GoodsName { get; set; }
    public string? WarehouseName { get; set; }
    public decimal Quantity { get; set; }
    public decimal Amount { get; set; }
    public decimal UnitPrice { get; set; }
    public string? OperatorName { get; set; }
    public string? MakerName { get; set; }
    public string? DeptName { get; set; }
    public DateTime MakeTime { get; set; }
    public string? AuditorName { get; set; }
    public DateTime? AuditTime { get; set; }
    public string? Remark { get; set; }
}

public class OutFlowStatsOutput
{
    public int OrdersCount { get; set; }
    public decimal GoodsQuantity { get; set; }
    public decimal GoodsAmount { get; set; }
}


